﻿using BCCommon;
using BCCommon.Enums;
using BCData.Common.DictionaryCategory;
using BCDto.Common.DictionaryCategory;
using BCDto.Sim.Admin.Admin;
using BCEntity.Common.DictionaryCategory;
using BCEntity.Common.EntityNameConst;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace BCService.Common.DictionaryCategory
{
    public class DictionaryCategoryService : IDictionaryCategoryService
    {
        private readonly IDatabaseContext databaseContext;
        private readonly IRedisService redisService;
        private readonly IDictionaryCategoryData dictionaryCategoryData;
        private readonly string key = string.Format("{0}", EntityNameConst.DictionaryCategoryEntity);

        public DictionaryCategoryService(IDatabaseContext databaseContext,
            IRedisService redisService,
            IDictionaryCategoryData dictionaryCategoryData)
        {
            this.databaseContext = databaseContext;
            this.redisService = redisService;
            this.dictionaryCategoryData = dictionaryCategoryData;
        }

        #region 检查字典分类是否存在
        public bool Exists(long dictionaryCategoryId)
        {
            return this.dictionaryCategoryData.Exists(dictionaryCategoryId).GetAwaiter().GetResult();
        }
        public bool Exists(string categoryCode)
        {
            return this.dictionaryCategoryData.Exists(categoryCode).GetAwaiter().GetResult();
        }
        #endregion

        #region 添加字典分类
        public DictionaryCategoryDto Add(DictionaryCategoryRequestDto requestDto,AdminDto adminDto)
        {
            if (this.Exists(requestDto.CategoryCode))
            {
                throw new ArgumentException("此分类编码已存在!");
            }
            if (!requestDto.CategoryCode.Contains(requestDto.SystemType.ToString()))
            {
                throw new ArgumentException("此分类编码格式不正确，编码开始位并非所选择的系统类型!");
            }
            int level = 0;
            string treeCode = string.Empty;
            if (requestDto.ParentDictionaryCategoryId.HasValue)
            {
                if (!this.dictionaryCategoryData.Exists(requestDto.ParentDictionaryCategoryId.Value).Result)
                {
                    throw new ArgumentException("父级分类不存在!");
                }
                var dto = this.Get(requestDto.ParentDictionaryCategoryId.Value);
                if(dto.SystemType!= requestDto.SystemType)
                {
                    throw new ArgumentException("此分类系统类型与父级分类系统类型应相同!");
                }
                level = dto.CategoryLevel + 1;
                treeCode = dto.TreeCode;
            }
           
            var entity = requestDto.As<DictionaryCategoryEntity>();
            entity.CreateAdminName = adminDto.FullName;
            entity.CreateAdminId = adminDto.AdminId;
            entity.CategoryLevel = level;
            entity.TreeCode = treeCode;

            databaseContext.BeginTransaction();
            var result = this.dictionaryCategoryData.Add(entity).GetAwaiter().GetResult();
            if (result.CategoryLevel > 0)
            {
                result = this.dictionaryCategoryData.UpdateTreeCode(result.DictionaryCategoryId, string.Format("{0},{1}", treeCode, result.DictionaryCategoryId)).Result;
            }
            databaseContext.Commit();
            this.redisService.DeleteMultipleKey(key, false);
            return result.As<DictionaryCategoryDto>();
        }
        #endregion

        #region 修改字典分类
        public DictionaryCategoryDto Update(DictionaryCategoryPutDto putDto,AdminDto adminDto)
        {
            if (!this.Exists(putDto.DictionaryCategoryId))
            {
                throw new ArgumentException("此记录不存在!");
            }
            if (this.Exists(putDto.CategoryCode))
            {
                throw new ArgumentException("此分类编码已存在!");
            }
            if (!putDto.CategoryCode.Contains(putDto.SystemType.ToString()))
            {
                throw new ArgumentException("此分类编码格式不正确，编码开始位并非所选择的系统类型!");
            }
            int level = 0;
            string treeCode = string.Empty;
            string oldTreeCode = string.Empty;
            if (putDto.ParentDictionaryCategoryId.HasValue)
            {
                if (!this.dictionaryCategoryData.Exists(putDto.ParentDictionaryCategoryId.Value).Result)
                {
                    throw new ArgumentException("父级分类不存在!");
                }
                var dto = this.Get(putDto.ParentDictionaryCategoryId.Value);
                if (dto.SystemType != putDto.SystemType)
                {
                    throw new ArgumentException("此分类系统类型与父级分类系统类型应相同!");
                }
                level = dto.CategoryLevel + 1;
                treeCode = dto.TreeCode;
            }
            var oldEntity = this.dictionaryCategoryData.GetEntity(putDto.DictionaryCategoryId).Result;
            oldTreeCode = oldEntity.TreeCode;
            
            var entity = putDto.As<DictionaryCategoryEntity>();
            treeCode = level > 0 ? string.Format("{0},{1}", treeCode, entity.DictionaryCategoryId) : entity.DictionaryCategoryId.ToString();

            if (oldTreeCode != treeCode)
            {
                throw new ArgumentException("分类系统及父级分类无法修改!");
            }

            entity.EditAdminName = adminDto.FullName;
            entity.EditAdminId = adminDto.AdminId;
            entity.CategoryLevel = level;
            entity.TreeCode = treeCode;

            var result = this.dictionaryCategoryData.Update(entity).GetAwaiter().GetResult();
            
            this.redisService.DeleteMultipleKey(key,false);
            return result.As<DictionaryCategoryDto>();
        }
        #endregion
        
        #region 删除字典分类
        public bool Delete(long dictionaryCategoryId)
        {
            if (!this.Exists(dictionaryCategoryId))
            {
                throw new ArgumentException("此记录不存在!");
            }

            var result = this.dictionaryCategoryData.Delete(dictionaryCategoryId).GetAwaiter().GetResult();
            this.redisService.DeleteMultipleKey(key, false);
            return result;
        }
        #endregion

        #region 获取字典分类
        public DictionaryCategoryDto Get(long dictionaryCategoryId)
        {
            string cacheKey = this.redisService.GetKey(key, dictionaryCategoryId);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = this.dictionaryCategoryData.GetEntity(dictionaryCategoryId).GetAwaiter().GetResult();
                return data;
            }, TimeSpan.FromMinutes(30));
            return result.As<DictionaryCategoryDto>();
        }
        #endregion

        #region 获取字典分类列表
        public IEnumerable<DictionaryCategoryDto> GetList(long? parentCategoryId)
        {
            string cacheKey = this.redisService.GetKey(key, parentCategoryId);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                return this.dictionaryCategoryData.GetList(parentCategoryId).GetAwaiter().GetResult();
            }, TimeSpan.FromMinutes(30));
            return result.As<IEnumerable<DictionaryCategoryDto>>();
        }
        public IEnumerable<DictionaryCategoryDto> GetList(BCSystemType systemType)
        {
            string cacheKey = this.redisService.GetKey(key, systemType);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                return this.dictionaryCategoryData.GetList(systemType).GetAwaiter().GetResult();
            }, TimeSpan.FromMinutes(30));
            return result.As<IEnumerable<DictionaryCategoryDto>>();
        }
        #endregion

        #region 获取字典分类分页
        public PageableList<DictionaryCategoryDto> Query(DateTime? start, DateTime? end, string sortName, bool? ascending, int pageIndex, int pageSize)
        {
            string cacheKey = this.redisService.GetKey(key, start, end, sortName, ascending, pageIndex, pageSize);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = this.dictionaryCategoryData.Query(start, end, sortName, ascending, pageIndex, pageSize).GetAwaiter().GetResult();
                return new PageableList<DictionaryCategoryDto>
                {
                    Count = data.Item2,
                    Items = data.Item1.As<IEnumerable<DictionaryCategoryDto>>(),
                    PageIndex = pageIndex,
                    PageSize = pageSize,
                    ServerTime = DateTime.Now
                };
            }, TimeSpan.FromMinutes(30));

            return result;
        }
        #endregion
    }
}